package com.xbongbong.paas.service.impl;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.message.domain.entity.PushSetEntity;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.help.ProUpdateHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.dto.ReturnCustomer2PublicAsyncDTO;
import com.xbongbong.paas.pojo.dto.ReturnCustomer2PublicDTO;
import com.xbongbong.paas.pojo.vo.ReturnCustomer2PublicAsyncVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.TransferBackRuleScriptService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.Entity;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.UpdateCustomerTeamScenesEnum;
import com.xbongbong.pro.enums.errorcodes.UserTeamErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.message.constant.ClueBackPushConstant;
import com.xbongbong.pro.message.constant.CustomerBackPushConstant;
import com.xbongbong.pro.message.enums.PushObjectTypeEnum;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.model.PushSetModel;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.message.pushset.CluePushSet;
import com.xbongbong.pro.message.pushset.CustomerPushSet;
import com.xbongbong.pro.message.service.MessageService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.ClueRuleEntity;
import com.xbongbong.saas.domain.entity.CustomerRuleEntity;
import com.xbongbong.saas.domain.entity.PublicGroupSeniorEntity;
import com.xbongbong.saas.domain.entity.RuleClueEntity;
import com.xbongbong.saas.domain.entity.RuleCustomerEntity;
import com.xbongbong.saas.domain.entity.RuleSeniorEntity;
import com.xbongbong.saas.domain.entity.TagEntity;
import com.xbongbong.saas.domain.entity.TagLinkEntity;
import com.xbongbong.saas.domain.entity.TransferBackRuleSeniorEntity;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.ClueSeniorRuleTypeEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.CustomerSeniorRuleTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.TagTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.factory.publicrule.CheckRuleMaxClueNum;
import com.xbongbong.saas.factory.publicrule.CheckRuleMaxCustomerNum;
import com.xbongbong.saas.factory.publicrule.CheckSeniorPublicBackRule;
import com.xbongbong.saas.factory.publicrule.CheckSeniorPublicTransferRule;
import com.xbongbong.saas.help.MarketManagementBusinessHelp;
import com.xbongbong.saas.help.PublicSeniorRuleHelp;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.PublicGroupSeniorModel;
import com.xbongbong.saas.model.TagLinkModel;
import com.xbongbong.saas.model.TagModel;
import com.xbongbong.saas.model.TransferBackRuleSeniorModel;
import com.xbongbong.saas.service.ClueUserService;
import com.xbongbong.saas.service.CustomerUserService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyModel;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author yanglei
 * @ProjectName xbb-pro
 * @Description: 公海高级模式 - 转移、退回定时脚本实现类
 * @date 2022/5/9 10:59
 */
@Service("transferBackRuleScriptService")
public class TransferBackRuleScriptServiceImpl implements TransferBackRuleScriptService {

    private static final Logger LOG = LoggerFactory.getLogger(TransferBackRuleScriptServiceImpl.class);

    @Resource
    private TransferBackRuleSeniorModel transferBackRuleSeniorModel;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private TagLinkModel tagLinkModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private CustomerRuleServiceImpl customerRuleService;
    @Resource
    private ClueUserModel clueUserModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private PublicSeniorRuleHelp publicSeniorRuleHelp;
    @Resource
    private MarketManagementBusinessHelp marketManagementBusinessHelp;
    @Resource
    private PublicGroupSeniorModel publicGroupSeniorModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private TagModel tagModel;
    @Resource
    private PushHelper pushHelper;
    @Resource
    private MessageService messageService;
    @Resource
    private PushSetModel pushSetModel;
    @Resource
    private ProUpdateHelp proUpdateHelp;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    private CheckSeniorPublicTransferRule checkSeniorTransferRule;
    @Resource
    private CheckSeniorPublicBackRule checkSeniorBackRule;
    @Resource
    private CheckRuleMaxCustomerNum checkRuleMaxCustomerNum;
    @Resource
    private CheckRuleMaxClueNum checkRuleMaxClueNum;
    @Resource
    private CustomerUserService customerUserService;
    @Resource
    private ClueUserService clueUserService;
    @Resource
    private ProBaseConfig proBaseConfig;


    /**
     * 校验参数
     * @param returnCustomer2PublicDTO 参数
     */
    @Override
    public ReturnCustomer2PublicAsyncDTO verifyParam(ReturnCustomer2PublicDTO returnCustomer2PublicDTO) throws XbbException {

        ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO = new ReturnCustomer2PublicAsyncDTO();

        String corpid = returnCustomer2PublicDTO.getCorpid();

        Integer notify = returnCustomer2PublicDTO.getNotify();

        Integer transfer = returnCustomer2PublicDTO.getTransfer();

        Integer back = returnCustomer2PublicDTO.getBack();

        if (!proBaseConfig.getXbbCode().equals(returnCustomer2PublicDTO.getKey())) {
            LOG.error("公海客户规则校验 密码错误，停止定时任务！");
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100066);
        }

        if (Objects.nonNull(notify) && !Objects.equals(notify, 1) && !Objects.equals(notify, 0)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015, "notify只能为0和1，0：不提醒 1：提醒");
        }

        boolean backOrTransfer = (Objects.nonNull(back) && !Objects.equals(back, 1) && !Objects.equals(back, 0)) || (Objects.nonNull(transfer) && !Objects.equals(transfer, 1) && !Objects.equals(transfer, 0));

        if (backOrTransfer) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015, "back只能为0和1，0：不退回 1：退回");
        }


        returnCustomer2PublicAsyncDTO.setCorpid(corpid);
        returnCustomer2PublicAsyncDTO.setNotify(Objects.equals(notify, 1));
        returnCustomer2PublicAsyncDTO.setBack(Objects.equals(back, 1) );
        returnCustomer2PublicAsyncDTO.setTransfer(Objects.equals(transfer, 1));
        return returnCustomer2PublicAsyncDTO;
    }

    @Override
    @Async(value = "returnPublicSeniorCustomerThreadPool")
    public XbbResponse<ReturnCustomer2PublicAsyncVO> returnCustomer2PublicSeniorAsync(ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO) throws XbbException {
        String[] split = returnCustomer2PublicAsyncDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        String singleCorpid = returnCustomer2PublicAsyncDTO.getCorpid();

        boolean back = returnCustomer2PublicAsyncDTO.getBack();

        boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        List<String> corpids = returnCustomer2PublicAsyncDTO.getCorpids();

        List<CompanyEntity> companyList;
        if (StringUtil.isNotEmpty(singleCorpid)) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", 0);
            params.put("corpid", singleCorpid);
            params.put("start", 0);
             params.put("pageNum", 1);
            companyList = companyModel.findEntitys(params);
            if (companyList.size() > 0) {
                seniorBackToPublic4Customer(singleCorpid, notify, back);
                LOG.info("公司（ID=" + companyList.get(0).getCorpid() + "）：客户退回公海池任务执行完成！");
            }
        } else {
            //多公司执行定时任务，去除未开启客户公海高级模式的公司
            publicSeniorRuleHelp.removeCorpidsByModel(corpids,true,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            for (String corpid : corpids) {
                seniorBackToPublic4Customer(corpid, notify, back);
                LOG.info("公司（ID=" + corpid + "）：客户退回公海池任务执行完成！");
            }
        }
        return null;
    }

    /**
     * 客户 - 单公司高级退回公海规则退回公海
     * @param corpid 公司id
     * @param back false不需要退回公海池   true退回公海池
     * @param notify false不需要即将退回提醒   true即将退回提醒
     * 创建时间 2022/4/18 4:25 PM
     * 修改时间 2022/4/18 4:25 PM
     * @author 杨磊
     * @since v1.0
     * @version v1.0
     */
    private void seniorBackToPublic4Customer(String corpid,boolean notify,boolean back) {
        LOG.info("returnCustomer_start:" + corpid);
        try {
            Integer businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
            //推送规则，此处规则现在只有是否推送给主负责人
            boolean isPushMain = getIsPushByAlias(corpid, PushTypeEnum.CUSTOMER_BACK_PUBLIC,PushObjectTypeEnum.MAINUSER.getAlias(),businessType);

            // 开启推送，将更新标签（删除该公司的所有退回公海池标签）
            if (notify) {
                tagLinkModel.deleteReturnPublicTags(corpid, TagTypeEnum.PUBLIC_CUSTOMER_RULE.getCode());
            }

            //获取公司所有的高级模式已启用的公海转移规则
            List<TransferBackRuleSeniorEntity> ruleSeniorEntityList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid, null,
                    businessType, Arrays.asList(CustomerSeniorRuleTypeEnum.BACK_RULE.getCode(),CustomerSeniorRuleTypeEnum.MAX_CUSTOMER_NUM_RULE.getCode()), BasicConstant.ONE);

            //获取提醒时间配置
            Integer advanceTime = publicSeniorRuleHelp.getRemindTimeByAlias(corpid, CompanyConfigEnum.PUBLIC_RULE_CUSTOMER_SENIOR_REMIND_TIME.getAlias());

            // 获取menuId，用来移除经销商数据
            PaasMenuEntity paasMenuEntity = paasMenuModel.getByAlias4Distributor(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getAlias(), corpid, DistributorMarkEnum.OTHER.getCode());

            //核心逻辑
            seniorBackCore4Customer(corpid,ruleSeniorEntityList,advanceTime,paasMenuEntity,isPushMain,back,notify);

            try {
                //一个公司操作完成，移除已打标签客户缓存
                paasRedisHelper.removeValue(RedisPrefixConstant.TAG_LINK_CUSTOMER_ID, corpid);
            } catch (Exception e) {
                LOG.error("搜索引擎更新客户\"即将退回公海池\"标签索引出错！公司Id：" + corpid);
            }
        } catch (Exception e) {
            LOG.error("seniorBackToPublic4Customer中出现了奇怪的异常, corpid:" + corpid, e);
        }
    }


    private void seniorBackCore4Customer(String corpid,List<TransferBackRuleSeniorEntity>
            ruleSeniorEntityList,Integer advanceTime,PaasMenuEntity paasMenuEntity,boolean isPushMain,boolean back,boolean notify) throws XbbException {
        Map<String, Object> userParam = new HashMap<>(5);
        userParam.put("corpid", corpid);
        //若是将异常的del状态的一起跑，会有很多user被跑到（前三家是近四万---近九万）
        userParam.put("del", 0);
        //一页200
        Integer pagerNum = 200;
        // 当前公司的用户总数
        Integer userCount = userModel.getEntitysCount(userParam);
        //总页数
        Integer pageTotal = userCount / pagerNum;
        //不能整除，页码加1
        if (userCount % pagerNum > 0) {
            ++pageTotal;
        }
        if (CollectionsUtil.isEmpty(ruleSeniorEntityList)){
            return;
        }
        List<Long> formIdIn = new ArrayList<>();
        ruleSeniorEntityList.forEach(item -> formIdIn.add(item.getFormId()));
        //获取表单字段启用情况
        Map<Long,Map<String, Integer>> formIdExplainMap = publicSeniorRuleHelp.getExplainOpenMap(corpid, formIdIn);
        //获取该表单开启标签列表
        Map<Long, List<Long>> formIdLabelIdMap = publicSeniorRuleHelp.getLabelIds4FormId(corpid,formIdIn);
        //如果模板下的所有分组，包括del = 1 的
        Map<Long,List<PublicGroupSeniorEntity>> formIdAllGroupIdMap = new HashMap<>();
        //获取模板启用并且未删除的分组
        Map<Long,List<Long>> formIdOpenGroupIdMap = new HashMap<>();
        //获取模板已经删除的分组
        Map<Long,List<Long>> formIdDeleteGroupIdMap = new HashMap<>();
        //获取已经当前模板开启的无分组客户、或无分组线索
        Map<Long, Long> formIdNoGroupMap = new HashMap<>();
        //获取已经当前模板开启的无分组客户、或无分组线索
        publicSeniorRuleHelp.getSpecialGroupIdMap(formIdAllGroupIdMap,formIdOpenGroupIdMap,formIdDeleteGroupIdMap, formIdNoGroupMap,corpid,formIdIn);
        for (int page = 0; page < pageTotal; page++) {
            Integer start = page * pagerNum;
            userParam.put("start", start);
            userParam.put("pageNum", pagerNum);
            userParam.put("columns", "corpid,user_id,name,role_ids,department");
            List<UserEntity> users = userModel.findEntitys(userParam);
            for (UserEntity user : users) {
                //当前员工负责客户数大于1万跳过处理
                Integer count = customerRuleService.mainCount(corpid, user.getUserId());
                if (count > 10000 || count <= 0) {
                    LOG.error("coount > 10000 || count <= 0 ,corpid:" + corpid + "userId:" + user.getUserId());
                    continue;
                }
                for (TransferBackRuleSeniorEntity rule : ruleSeniorEntityList) {
                    //执行完一条规则，员工拥有的客户可能会发生变化
                    Integer ruleType = rule.getType();
                    Long formId = rule.getFormId();
                    Map<String, Integer> explainOpenMap = formIdExplainMap.getOrDefault(formId,new HashMap<>());
                    List<Long> labelIds = formIdLabelIdMap.getOrDefault(formId,new ArrayList<>());
                    List<PublicGroupSeniorEntity> allGroupList = formIdAllGroupIdMap.getOrDefault(formId, new ArrayList<>());
                    List<Long> openGroupIdList = formIdOpenGroupIdMap.getOrDefault(formId, new ArrayList<>());
                    List<Long> deleteGroupIdList = formIdDeleteGroupIdMap.getOrDefault(formId, new ArrayList<>());
                    Long noGroupId = formIdNoGroupMap.getOrDefault(formId, 0L);
                    if (!Objects.equals(ruleType, CustomerSeniorRuleTypeEnum.MAX_CUSTOMER_NUM_RULE.getCode())) {
                        backToPublic4CustomerNotMaxCount(corpid, user, back, notify, rule, advanceTime, isPushMain, paasMenuEntity.getId(),explainOpenMap,labelIds,
                                openGroupIdList,  deleteGroupIdList, noGroupId,allGroupList);
                    } else {
                        //客户最大客户数规则，公海高级模式没动到这块，所以还用老的代码
                        backToPublic4CustomerMaxCount(corpid, user, back, notify, rule, advanceTime, isPushMain, paasMenuEntity.getId());
                    }
                }
            }
        }
    }

    /**
     * 客户公海高级模式 - 高级退回规则
     * @param corpid 公司id
     * @param user 当前员工
     * @param back 是否退回
     * @param notify 是否提醒
     * @param rule 退回规则
     * @param advanceTime 提醒时间
     * @param isPushMain 是否推送主负责人
     * @param explainOpenMap 当前表单开启的字段
     * @param labelIds 当前表单开启的标签id
     * @param openGroupIdList 当前表单开启的分组id
     * @param deleteGroupIdList 当前删除的分组id
     * @param noGroupId 当前表单无分组id
     * @param allGroupList 当前表单的全部分组
     * @param menuId
     */
    private void backToPublic4CustomerNotMaxCount(String corpid, UserEntity user, boolean back, boolean notify,
                                  TransferBackRuleSeniorEntity rule, Integer advanceTime, boolean isPushMain, Long menuId,Map<String,
                                  Integer> explainOpenMap,List<Long> labelIds,List<Long> openGroupIdList, List<Long> deleteGroupIdList,Long noGroupId,List<PublicGroupSeniorEntity> allGroupList) {
        Integer ruleType = rule.getType();
        Integer businessType = rule.getBusinessType();
        //执行完一条规则，员工拥有的客户可能会发生变化，不能用page的分页
        Long startId = 0L;
        Integer pageNum = 1000;
        List<Long> idIn = customerUserModel.getDataIdList4Rule(corpid, 1, user.getUserId(), startId, pageNum);
        while (CollectionsUtil.isNotEmpty(idIn)){
            List<RuleSeniorEntity> backCustomerList = new ArrayList<>();
            //最后的一个id作为起始id
            startId = idIn.get(idIn.size() - 1);
            try {
                if(back){
                    backCustomerList = checkSeniorBackRule.getSeniorBackCustomerList(user, rule, idIn,null,menuId,explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                    if (CollectionsUtil.isNotEmpty(backCustomerList)) {
                        return2SeniorPublic(user, backCustomerList,  businessType);
                        pushReturnMessage(user, backCustomerList, rule.getBusinessType());
                    }
                }
                if(notify){
                    List<RuleSeniorEntity> notifyCustomerList = checkSeniorBackRule.getSeniorBackCustomerList(user, rule, idIn,advanceTime,menuId,explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                    //去除已经退回的客户
                    if(CollectionsUtil.isNotEmpty(notifyCustomerList) && CollectionsUtil.isNotEmpty(backCustomerList)){
                        List<Long> backIds = backCustomerList.stream().map(RuleSeniorEntity::getId).collect(Collectors.toList());
                        notifyCustomerList = notifyCustomerList.stream().filter(item -> !backIds.contains(item.getId())).collect(Collectors.toList());
                    }
                    if (CollectionsUtil.isNotEmpty(notifyCustomerList)) {
                        tagBackOrTransferPublic(corpid, notifyCustomerList,businessType,ruleType);
                        if (isPushMain){
                            pushBackTagMessage(user, notifyCustomerList,businessType);
                        }
                    }
                }
            }catch (Exception e) {
                LOG.error("corpid:{},startId:{},客户高级模式退回规则执行出错",corpid,startId, e);
                //startId = idIn.get(idIn.size() - 1);
                idIn = customerUserModel.getDataIdList4Rule(corpid, 1, user.getUserId(), startId, pageNum);
                continue;
            }
            idIn = customerUserModel.getDataIdList4Rule(corpid, 1, user.getUserId(), startId, pageNum);
        }
    }



    /**
     * 客户公海高级模式 - 最大客户数退回公海池（员工逻辑）
     * @param corpid
     * @param user
     * @param back
     * @param notify
     * @param ruleSenior
     * @param advanceTime
     * @param isPushMain
     */
    public void backToPublic4CustomerMaxCount(String corpid, UserEntity user, boolean back, boolean notify,
                                       TransferBackRuleSeniorEntity ruleSenior, Integer advanceTime, boolean isPushMain, Long menuId) throws XbbException {
        Long startTime = DateTimeUtil.getInt();
        List<RuleCustomerEntity> customerList = customerModel.getMainCustomerListByUserId(corpid, user.getUserId(), null, null, null, null, null, null, menuId);
        Integer ruleType = ruleSenior.getType();
        Integer businessType = ruleSenior.getBusinessType();
        CustomerRuleEntity customerRule = new CustomerRuleEntity();

        publicSeniorRuleHelp.copyRuleEntity(ruleSenior,customerRule,null,businessType);

        List<RuleCustomerEntity> backCustomerList = null;
        if(back){
            try {
                backCustomerList = checkRuleMaxCustomerNum.getBackCustomerList(user, customerRule, customerList);
            } catch (XbbException e) {
                LOG.error("corpid:" + corpid + "ruleType:" + ruleType, e);
                return ;
            }
            if (CollectionsUtil.isNotEmpty(backCustomerList)) {
                List<RuleSeniorEntity> backSeniorList = copyBackCustomerList(backCustomerList, null);
                return2SeniorPublic(user, backSeniorList, businessType);
                pushReturnMessage(user, backSeniorList, businessType);
            }
        }
        //最大客户数没有打标签的逻辑
    }

    @Override
    @Async(value = "returnPublicSeniorClueThreadPool")
    public XbbResponse<ReturnCustomer2PublicAsyncVO> returnClue2PublicSeniorAsync(ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO) throws XbbException {
        String[] split = returnCustomer2PublicAsyncDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        String singleCorpid = returnCustomer2PublicAsyncDTO.getCorpid();

        boolean back = returnCustomer2PublicAsyncDTO.getBack();

        boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        List<String> corpids = returnCustomer2PublicAsyncDTO.getCorpids();

        List<CompanyEntity> companyList;
        if (StringUtil.isNotEmpty(singleCorpid)) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", 0);
            params.put("corpid", singleCorpid);
            params.put("start", 0);
            params.put("pageNum", 1);
            companyList = companyModel.findEntitys(params);
            if (companyList.size() > 0) {
                seniorBackToPublic4Clue(singleCorpid, notify, back);
                LOG.info("公司（ID=" + companyList.get(0).getCorpid() + "）：线索退回公海池任务执行完成！");
            }
        } else {
            //多公司执行定时任务，去除未开启线索公海高级模式的公司
            publicSeniorRuleHelp.removeCorpidsByModel(corpids,true,XbbRefTypeEnum.CLUE.getCode());
            for (String corpid : corpids) {
                seniorBackToPublic4Clue(corpid, notify, back);
                LOG.info("公司（ID=" + corpid + "）：线索退回公海池任务执行完成！");
            }
        }
        return null;
    }


    /**
     * 线索 - 单公司高级退回公海规则退回公海
     * @param corpid 公司id
     * @param back false不需要退回公海池   true退回公海池
     * @param notify false不需要即将退回提醒   true即将退回提醒
     * 创建时间 2022/5/9 4:25 PM
     * 修改时间 2022/5/9 4:25 PM
     * @author 杨磊
     * @since v1.0
     * @version v1.0
     */
    private void seniorBackToPublic4Clue(String corpid,boolean notify,boolean back) {
        LOG.info("returnClueSenior_start:" + corpid);
        try {
            Boolean standardWithFeeType = marketManagementBusinessHelp.isStandardWithFeeType(corpid);
            if (standardWithFeeType) {
                LOG.info("该公司是标准版，不执行线索退回公海池脚本:corpid=====" + corpid);
                return;
            }

            boolean enableWithApp = marketManagementBusinessHelp.isEnableWithApp(corpid);
            if (!enableWithApp) {
                LOG.info("该公司的线索应用未开启，不执行线索退回公海池脚本:corpid=====" + corpid);
                return;
            }

            PaasMenuEntity menuEntity = paasMenuModel.getByAlias(XbbRefTypeEnum.CLUE.getAlias(), corpid);
            if (Objects.isNull(menuEntity) || !Objects.equals(menuEntity.getEnable(), BasicConstant.ONE)) {
                LOG.info("该公司的线索菜单未开启，不执行线索退回公海池脚本:corpid=====" + corpid);
                return;
            }

            //推送规则，此处规则现在只有是否推送给主负责人
            Integer businessType = XbbRefTypeEnum.CLUE.getCode();
            boolean isPushMain = getIsPushByAlias(corpid, PushTypeEnum.CUSTOMER_BACK_PUBLIC,PushObjectTypeEnum.MAINUSER.getAlias(),businessType);

            // 开启推送，将更新标签（删除该公司的所有退回公海池标签）
            if (notify) {
                tagLinkModel.deleteReturnPublicTags(corpid, TagTypeEnum.PUBLIC_CLUE_RULE.getCode());
            }

            //获取公司所有的线索高级模式已启用的公海退回规则
            List<TransferBackRuleSeniorEntity> ruleSeniorEntityList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid, null,
                    businessType, Arrays.asList(ClueSeniorRuleTypeEnum.BACK_RULE.getCode(),ClueSeniorRuleTypeEnum.MAX_CLUE_NUM_RULE.getCode()),BasicConstant.ONE);

            //获取提醒时间配置
            Integer advanceTime = publicSeniorRuleHelp.getRemindTimeByAlias(corpid, CompanyConfigEnum.PUBLIC_RULE_CLUE_SENIOR_REMIND_TIME.getAlias());

            //核心逻辑
            seniorBackCore4Clue(corpid,ruleSeniorEntityList,advanceTime,isPushMain,back,notify);

            try {
                //一个公司操作完成，移除已打标签客户缓存
                paasRedisHelper.removeValue(RedisPrefixConstant.TAG_LINK_CLUE_ID, corpid);
            } catch (Exception e) {
                LOG.error("搜索引擎更新线索\"即将退回公海池\"标签索引出错！公司Id：" + corpid);
            }
        } catch (Exception e) {
            LOG.error("seniorBackToPublic4Clue中出现了奇怪的异常, corpid:" + corpid, e);
        }
    }


    private void seniorBackCore4Clue(String corpid,List<TransferBackRuleSeniorEntity>
            ruleSeniorEntityList,Integer advanceTime,boolean isPushMain,boolean back,boolean notify) throws XbbException {
        Map<String, Object> userParam = new HashMap<>(5);
        userParam.put("corpid", corpid);
        //若是将异常的del状态的一起跑，会有很多user被跑到（前三家是近四万---近九万）
        userParam.put("del", 0);
        //一页200
        Integer pagerNum = 200;
        // 当前公司的用户总数
        Integer userCount = userModel.getEntitysCount(userParam);
        //总页数
        Integer pageTotal = userCount / pagerNum;
        //不能整除，页码加1
        if (userCount % pagerNum > 0) {
            ++pageTotal;
        }
        Map<String, Object> countParam = new HashMap<>();
        countParam.put("corpid", corpid);
        countParam.put("isMain", 1);
        countParam.put("del", 0);

        List<Long> formIdIn = new ArrayList<>();
        ruleSeniorEntityList.forEach(item -> formIdIn.add(item.getFormId()));
        //获取表单字段启用情况
        Map<Long,Map<String, Integer>> formIdExplainMap = publicSeniorRuleHelp.getExplainOpenMap(corpid, formIdIn);
        //获取该表单开启标签列表
        Map<Long, List<Long>> formIdLabelIdMap = publicSeniorRuleHelp.getLabelIds4FormId(corpid,formIdIn);
        //如果模板下的所有分组，包括del = 1 的
        Map<Long,List<PublicGroupSeniorEntity>> formIdAllGroupIdMap = new HashMap<>();
        //获取模板启用并且未删除的分组
        Map<Long,List<Long>> formIdOpenGroupIdMap = new HashMap<>();
        //获取模板已经删除的分组
        Map<Long,List<Long>> formIdDeleteGroupIdMap = new HashMap<>();
        //获取已经当前模板开启的无分组客户、或无分组线索
        Map<Long, Long> formIdNoGroupMap = new HashMap<>();
        //获取已经当前模板开启的无分组客户、或无分组线索
        publicSeniorRuleHelp.getSpecialGroupIdMap(formIdAllGroupIdMap,formIdOpenGroupIdMap,formIdDeleteGroupIdMap, formIdNoGroupMap,corpid,formIdIn);

        for (int page = 0; page < pageTotal; page++) {
            Integer start = page * pagerNum;
            userParam.put("start", start);
            userParam.put("pageNum", pagerNum);
            userParam.put("columns", "corpid,user_id,name,role_ids,department");
            List<UserEntity> users = userModel.findEntitys(userParam);
            for (UserEntity user : users) {
                //当前员工负责客户数大于1万跳过处理
                countParam.put("userId", user.getUserId());
                Integer count = clueUserModel.getEntitysCount(countParam);
                if (count > 10000 || count <= 0) {
                    LOG.error("coount > 10000 || count <= 0,corpid:" + corpid + "userId:" + user.getUserId());
                    continue;
                }
                for (TransferBackRuleSeniorEntity rule : ruleSeniorEntityList) {
                    //执行完一条规则，员工拥有的线索可能会发生变化
                    Integer ruleType = rule.getType();
                    Long formId = rule.getFormId();
                    Map<String, Integer> explainOpenMap = formIdExplainMap.getOrDefault(formId,new HashMap<>());
                    List<Long> labelIds = formIdLabelIdMap.getOrDefault(formId,new ArrayList<>());
                    List<PublicGroupSeniorEntity> allGroupList = formIdAllGroupIdMap.getOrDefault(formId, new ArrayList<>());
                    List<Long> openGroupIdList = formIdOpenGroupIdMap.getOrDefault(formId, new ArrayList<>());
                    List<Long> deleteGroupIdList = formIdDeleteGroupIdMap.getOrDefault(formId, new ArrayList<>());
                    Long noGroupId = formIdNoGroupMap.getOrDefault(formId, 0L);
                    //最大线索数逻辑不能用分页处理区分处理
                    if (!Objects.equals(ruleType, ClueSeniorRuleTypeEnum.MAX_CLUE_NUM_RULE.getCode())) {
                        backToPublic4ClueNotMaxCount(corpid, user, back, notify, rule, advanceTime, isPushMain,explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                    } else {
                        //最大线索数规则没有好的方案 还是以原来的方案处理
                        backToPublic4ClueMaxCount(corpid, user, back, notify, rule, advanceTime, isPushMain);
                    }
                }
            }
        }
    }

    /**
     * 线索公海高级模式 - 高级退回规则
     * @param corpid 公司id
     * @param user 当前员工
     * @param back 是否退回
     * @param notify 是否提醒
     * @param rule 退回规则
     * @param advanceTime 提醒时拿
     * @param isPushMain 是否推送主负责人
     * @param explainOpenMap 当前表单开启的字段
     * @param labelIds 当前表单开启的标签id
     * @param openGroupIdList 当前表单开启的分组id
     * @param deleteGroupIdList 当前删除的分组id
     * @param noGroupId 当前表单无分组id
     * @param allGroupList 当前表单的全部分组
     */
    void backToPublic4ClueNotMaxCount(String corpid, UserEntity user, boolean back, boolean notify,
                                      TransferBackRuleSeniorEntity rule, Integer advanceTime, boolean isPushMain,Map<String, Integer> explainOpenMap,List<Long> labelIds,
                                      List<Long> openGroupIdList, List<Long> deleteGroupIdList,Long noGroupId,List<PublicGroupSeniorEntity> allGroupList) throws XbbException {
        Integer ruleType = rule.getType();
        Integer businessType = rule.getBusinessType();
        //执行完一条规则，员工拥有的线索数可能会发生变化，不能用page的分页
        Long startId = 0L;
        Integer pageNum = 1000;
        List<Long> idIn = clueUserModel.getDataIdList4Rule(corpid, 1, user.getUserId(), startId, pageNum);
        while (CollectionsUtil.isNotEmpty(idIn)){
            List<RuleSeniorEntity> backClueList = new ArrayList<>();
            //最后的一个id作为起始id
            startId = idIn.get(idIn.size() - 1);
            try {
                if(back) {
                    backClueList = checkSeniorBackRule.getSeniorBackClueList(user, rule, idIn, null, explainOpenMap, labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                    if (CollectionsUtil.isNotEmpty(backClueList)) {
                        return2SeniorPublic(user, backClueList, businessType);
                        pushReturnMessage(user, backClueList, rule.getBusinessType());
                    }
                }
                if(notify){
                    List<RuleSeniorEntity> notifyClueList = checkSeniorBackRule.getSeniorBackClueList(user, rule, idIn,advanceTime,explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                    if(CollectionsUtil.isNotEmpty(backClueList) && CollectionsUtil.isNotEmpty(notifyClueList)){
                        //去除已经退回的线索
                        List<Long> backIds = backClueList.stream().map(RuleSeniorEntity::getId).collect(Collectors.toList());
                        notifyClueList = notifyClueList.stream().filter(item -> !backIds.contains(item.getId())).collect(Collectors.toList());
                    }
                    if (CollectionsUtil.isNotEmpty(notifyClueList)) {
                        tagBackOrTransferPublic(corpid, notifyClueList,businessType,ruleType);
                        if (isPushMain){
                            pushBackTagMessage(user, notifyClueList,businessType);
                        }
                    }
                }
            } catch (XbbException e) {
                LOG.error("corpid:" + corpid + "线索高级退回规则执行出错", e);
                //startId = idIn.get(idIn.size() - 1);
                idIn = clueUserModel.getDataIdList4Rule(corpid, 1, user.getUserId(), startId, pageNum);
                continue;
            }
            idIn = clueUserModel.getDataIdList4Rule(corpid, 1, user.getUserId(), startId, pageNum);
        }
    }



    /**
     * 线索公海高级模式 - 最大线索数退回公海池（员工逻辑）
     * @param corpid
     * @param user
     * @param back
     * @param notify
     * @param ruleSenior
     * @param advanceTime
     * @param isPushMain
     */
    public void backToPublic4ClueMaxCount(String corpid, UserEntity user, boolean back, boolean notify,
                                              TransferBackRuleSeniorEntity ruleSenior, Integer advanceTime, boolean isPushMain) throws XbbException {
        List<RuleClueEntity> clueList = clueModel.getMainClueListByUserId(corpid, user.getUserId(), null, null, null, null, null, null);
        Integer ruleType = ruleSenior.getType();
        Integer businessType = ruleSenior.getBusinessType();
        ClueRuleEntity clueRule = new ClueRuleEntity();
        publicSeniorRuleHelp.copyRuleEntity(ruleSenior,null,clueRule,businessType);
        List<RuleClueEntity> backClueList = null;
        if(back){
            try {
                backClueList = checkRuleMaxClueNum.getBackClueList(user, clueRule, clueList);
            } catch (XbbException e) {
                LOG.error("corpid:" + corpid + "ruleType:" + ruleType, e);
                return ;
            }
            if (CollectionsUtil.isNotEmpty(backClueList)) {
                List<RuleSeniorEntity> backSeniorList = copyBackCustomerList(null, backClueList);
                return2SeniorPublic(user, backSeniorList, businessType);
                pushReturnMessage(user, backSeniorList, businessType);
            }
        }
        //最大线索数没有打标签的逻辑
    }

    @Override
    @Async(value = "transferPublicSeniorCustomerThreadPool")
    public XbbResponse<ReturnCustomer2PublicAsyncVO> transferCustomer2PublicSeniorAsync(ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO) throws XbbException {
        String[] split = returnCustomer2PublicAsyncDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        String singleCorpid = returnCustomer2PublicAsyncDTO.getCorpid();

        boolean transfer = returnCustomer2PublicAsyncDTO.getTransfer();

        boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        List<String> corpids = returnCustomer2PublicAsyncDTO.getCorpids();

        List<CompanyEntity> companyList;
        if (StringUtil.isNotEmpty(singleCorpid)) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", 0);
            params.put("corpid", singleCorpid);
            params.put("start", 0);
            params.put("pageNum", 1);
            companyList = companyModel.findEntitys(params);
            if (companyList.size() > 0) {
                seniorTransferToPublic4Customer(singleCorpid, notify, transfer);
                LOG.info("公司（ID=" + companyList.get(0).getCorpid() + "）：转移公海池任务执行完成！");
            }
        } else {
            //多公司执行定时任务，去除未开启客户公海高级模式的公司
            publicSeniorRuleHelp.removeCorpidsByModel(corpids,true,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            for (String corpid : corpids) {
                seniorTransferToPublic4Customer(corpid, notify, transfer);
                LOG.info("公司（ID=" + corpid + "）：转移公海池任务执行完成！");
            }
        }
        return null;
    }


    @Override
    @Async(value = "transferPublicSeniorClueThreadPool")
    public XbbResponse<ReturnCustomer2PublicAsyncVO> transferClue2PublicSeniorAsync(ReturnCustomer2PublicAsyncDTO returnCustomer2PublicAsyncDTO) throws XbbException {
        String[] split = returnCustomer2PublicAsyncDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        String singleCorpid = returnCustomer2PublicAsyncDTO.getCorpid();

        boolean transfer = returnCustomer2PublicAsyncDTO.getTransfer();

        boolean notify = returnCustomer2PublicAsyncDTO.getNotify();

        List<String> corpids = returnCustomer2PublicAsyncDTO.getCorpids();

        List<CompanyEntity> companyList;
        if (StringUtil.isNotEmpty(singleCorpid)) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", 0);
            params.put("corpid", singleCorpid);
            params.put("start", 0);
            params.put("pageNum", 1);
            companyList = companyModel.findEntitys(params);
            if (companyList.size() > 0) {
                seniorTransferToPublic4Clue(singleCorpid, notify, transfer);
                LOG.info("公司（ID=" + companyList.get(0).getCorpid() + "）：转移公海池任务执行完成！");
            }
        } else {
            //多公司执行定时任务，去除未开启线索公海高级模式的公司
            publicSeniorRuleHelp.removeCorpidsByModel(corpids,true,XbbRefTypeEnum.CLUE.getCode());
            for (String corpid : corpids) {
                seniorTransferToPublic4Clue(corpid, notify, transfer);
                LOG.info("公司（ID=" + corpid + "）：转移公海池任务执行完成！");
            }
        }
        return null;
    }

    /**
     * 客户 - 单公司高级转移公海规则转移公海
     * @param corpid 公司id
     * @param transfer false不需要退回公海池   true退回公海池
     * @param notify false不需要即将退回提醒   true即将退回提醒
     * 创建时间 2022/5/9 4:25 PM
     * 修改时间 2022/5/9 4:25 PM
     * @author 杨磊
     * @since v1.0
     * @version v1.0
     */
    private void seniorTransferToPublic4Customer(String corpid,boolean   notify,boolean transfer) {
        LOG.info("transferCustomer_start:" + corpid);
        try {
            //因为转移是公海池之间的转移，不存在负责人，所以也就不存在上级主管,所以转移和即将转移消息推送这里只需要cropid
            UserEntity userEntity = new UserEntity();
            userEntity.setCorpid(corpid);
            //转移推送规则，获取是否推送给分组管理员和分组成员
            Integer businessType = XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode();
            Integer ruleType = CustomerSeniorRuleTypeEnum.TRANSFER_RULE.getCode();
            boolean isPushGroupManager = getIsPushByAlias(corpid, PushTypeEnum.CUSTOMER_TRANSFER_PUBLIC, PushObjectTypeEnum.PUBLIC_GROUP_MANAGER.getAlias(),businessType);
            boolean isPushGroupUser = getIsPushByAlias(corpid, PushTypeEnum.CUSTOMER_TRANSFER_PUBLIC, PushObjectTypeEnum.PUBLIC_GROUP_USER.getAlias(),businessType);

            //开启推送，将更新标签（删除该公司的所有转移公海池标签）
            if (notify) {
                tagLinkModel.deleteReturnPublicTags(corpid, TagTypeEnum.TRANSFER_CUSTOMER_RULE.getCode());
            }

            //获取公司所有的高级模式已启用的公海退回规则
            List<TransferBackRuleSeniorEntity> ruleSeniorList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid, null,
                    businessType, Arrays.asList(ruleType),BasicConstant.ONE);

            if (CollectionsUtil.isEmpty(ruleSeniorList)){
                return;
            }
            //获取提醒时间配置
            Integer advanceTime = publicSeniorRuleHelp.getRemindTimeByAlias(corpid, CompanyConfigEnum.TRANSFER_RULE_CUSTOMER_SENIOR_REMIND_TIME.getAlias());

            // 获取该公司已启用并且未删除的公海分组,不分表单模板
            List<PublicGroupSeniorEntity> groupSeniorList = publicGroupSeniorModel.findEntityByStatus(corpid, null, BasicConstant.ONE);

            List<Long> formIdIn = new ArrayList<>();
            ruleSeniorList.forEach(item -> formIdIn.add(item.getFormId()));
            //获取表单字段启用情况
            Map<Long,Map<String, Integer>> formIdExplainMap = publicSeniorRuleHelp.getExplainOpenMap(corpid, formIdIn);
            //获取该表单开启标签列表
            Map<Long, List<Long>> formIdLabelIdMap = publicSeniorRuleHelp.getLabelIds4FormId(corpid,formIdIn);
            //如果模板下的所有分组，包括del = 1 的
            Map<Long,List<PublicGroupSeniorEntity>> formIdAllGroupIdMap = new HashMap<>();
            //获取模板启用并且未删除的分组
            Map<Long,List<Long>> formIdOpenGroupIdMap = new HashMap<>();
            //获取模板已经删除的分组
            Map<Long,List<Long>> formIdDeleteGroupIdMap = new HashMap<>();
            //获取已经当前模板开启的无分组客户、或无分组线索
            Map<Long, Long> formIdNoGroupMap = new HashMap<>();
            //获取已经当前模板开启的无分组客户、或无分组线索
            publicSeniorRuleHelp.getSpecialGroupIdMap(formIdAllGroupIdMap,formIdOpenGroupIdMap,formIdDeleteGroupIdMap, formIdNoGroupMap,corpid,formIdIn);
            //核心逻辑
            for (TransferBackRuleSeniorEntity rule : ruleSeniorList) {
                Long formId = rule.getFormId();
                Map<String, Integer> explainOpenMap = formIdExplainMap.getOrDefault(formId,new HashMap<>());
                List<Long> labelIds = formIdLabelIdMap.getOrDefault(formId,new ArrayList<>());
                List<PublicGroupSeniorEntity> allGroupList = formIdAllGroupIdMap.getOrDefault(formId, new ArrayList<>());
                List<Long> openGroupIdList = formIdOpenGroupIdMap.getOrDefault(formId, new ArrayList<>());
                List<Long> deleteGroupIdList = formIdDeleteGroupIdMap.getOrDefault(formId, new ArrayList<>());
                Long noGroupId = formIdNoGroupMap.getOrDefault(formId, 0L);
                Long totalCount = publicSeniorRuleHelp.getPublicCountByForm(corpid, businessType, formId);
                LOG.warn("当前模板的公海池数据总数：totalCount{}", totalCount);
                int pageSize = 1000;
                Long gtId = 0L;
                int pageNum = (int) (totalCount % pageSize > 0 ? totalCount / pageSize + 1 : totalCount / pageSize);
                for (int currentPage = 1; currentPage <= pageNum; currentPage++) {
                    List<Long> dataIdIn = publicSeniorRuleHelp.getDataIdList4Public(gtId,corpid, rule.getFormId(), BasicConstant.ONE, businessType, pageSize);
                    if (CollectionsUtil.isEmpty(dataIdIn)){
                        break;
                    }
                    //获取当前页最后一个元素的id
                    gtId = dataIdIn.get(dataIdIn.size() - 1);
                    List<RuleSeniorEntity> backCustomerList =  new ArrayList<>();
                    try {
                        if(transfer) {
                            backCustomerList = checkSeniorTransferRule.getSeniorBackCustomerList(null, rule, dataIdIn, null, null, explainOpenMap, labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                            LOG.warn("公司id:{},当前页：{}",corpid,currentPage);
                            if (CollectionsUtil.isNotEmpty(backCustomerList)) {
                                transfer2SeniorPublic(corpid, backCustomerList, businessType);
                                pushTransferMessage(userEntity, backCustomerList, businessType, groupSeniorList);
                            }
                        }
                        if(notify){
                            List<RuleSeniorEntity>  notifyCustomerList = checkSeniorTransferRule.getSeniorBackCustomerList(null, rule, dataIdIn,advanceTime,null,explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                            if(CollectionsUtil.isNotEmpty(backCustomerList) && CollectionsUtil.isNotEmpty(notifyCustomerList)){
                                //去除已经转移的客户
                                List<Long> backIds = backCustomerList.stream().map(RuleSeniorEntity::getId).collect(Collectors.toList());
                                notifyCustomerList = notifyCustomerList.stream().filter(item -> !backIds.contains(item.getId())).collect(Collectors.toList());
                            }
                            if (CollectionsUtil.isNotEmpty(notifyCustomerList)) {
                                tagBackOrTransferPublic(corpid, notifyCustomerList,businessType,ruleType);
                                pushTransferTagMessage(groupSeniorList,userEntity, notifyCustomerList,businessType,isPushGroupManager,isPushGroupUser);
                            }
                        }
                    } catch (XbbException e) {
                        LOG.error("corpid:" + corpid + "当前报错页数:{}" + currentPage, e);
                    }
                }
            }
            try {
                //一个公司操作完成，移除已打标签客户缓存
                paasRedisHelper.removeValue(RedisPrefixConstant.TAG_LINK_TRANSFER_CUSTOMER_ID, corpid);
            } catch (Exception e) {
                LOG.error("搜索引擎更新客户\"即将转移公海池\"标签索引出错！公司Id：" + corpid);
            }
        } catch (Exception e) {
            LOG.error("backToPublic中出现了奇怪的异常, corpid:" + corpid, e);
        }
    }


    /**
     * 线索 - 单公司高级转移公海规则退回公海
     * @param corpid 公司id
     * @param transfer false不需要退回公海池   true退回公海池
     * @param notify false不需要即将退回提醒   true即将退回提醒
     * 创建时间 2022/5/9 4:25 PM
     * 修改时间 2022/5/9 4:25 PM
     * @author 杨磊
     * @since v1.0
     * @version v1.0
     */
    private void seniorTransferToPublic4Clue(String corpid,boolean notify,boolean transfer) {
        LOG.info("transferClue_start:" + corpid);
        try {
            //因为转移是公海池之间的转移，不存在负责人，所以也就不存在上级主管,所以转移和即将转移消息推送这里只需要cropid
            UserEntity userEntity = new UserEntity();
            userEntity.setCorpid(corpid);
            //转移推送规则，获取是否推送给分组管理员和分组成员
            Integer businessType = XbbRefTypeEnum.CLUE.getCode();
            Integer ruleType = ClueSeniorRuleTypeEnum.TRANSFER_RULE.getCode();
            boolean isPushGroupManager = getIsPushByAlias(corpid, PushTypeEnum.CLUE_TRANSFER_PUBLIC, PushObjectTypeEnum.PUBLIC_GROUP_MANAGER.getAlias(),businessType);
            boolean isPushGroupUser = getIsPushByAlias(corpid, PushTypeEnum.CLUE_TRANSFER_PUBLIC, PushObjectTypeEnum.PUBLIC_GROUP_USER.getAlias(),businessType);

            //开启推送，将更新标签（删除该公司的所有转移公海池标签）
            if (notify) {
                tagLinkModel.deleteReturnPublicTags(corpid, TagTypeEnum.TRANSFER_CLUE_RULE.getCode());
            }

            //获取公司所有的高级模式已启用的公海退回规则
            List<TransferBackRuleSeniorEntity> ruleSeniorList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid, null,
                    businessType, Arrays.asList(ClueSeniorRuleTypeEnum.TRANSFER_RULE.getCode()),BasicConstant.ONE);
            if (CollectionsUtil.isEmpty(ruleSeniorList)){
                return;
            }
            //获取提醒时间配置
            Integer advanceTime = publicSeniorRuleHelp.getRemindTimeByAlias(corpid, CompanyConfigEnum.TRANSFER_RULE_CLUE_SENIOR_REMIND_TIME.getAlias());

            // 获取该公司已启用并且未删除的公海分组,不分表单模板
            List<PublicGroupSeniorEntity> groupSeniorList = publicGroupSeniorModel.findEntityByStatus(corpid, null, BasicConstant.ONE);

            List<Long> formIdIn = new ArrayList<>();
            ruleSeniorList.forEach(item -> formIdIn.add(item.getFormId()));
            //获取表单字段启用情况
            Map<Long,Map<String, Integer>> formIdExplainMap = publicSeniorRuleHelp.getExplainOpenMap(corpid, formIdIn);
            //获取该表单开启标签列表
            Map<Long, List<Long>> formIdLabelIdMap = publicSeniorRuleHelp.getLabelIds4FormId(corpid,formIdIn);
            //如果模板下的所有分组，包括del = 1 的
            Map<Long,List<PublicGroupSeniorEntity>> formIdAllGroupIdMap = new HashMap<>();
            //获取模板启用并且未删除的分组
            Map<Long,List<Long>> formIdOpenGroupIdMap = new HashMap<>();
            //获取模板已经删除的分组
            Map<Long,List<Long>> formIdDeleteGroupIdMap = new HashMap<>();
            //获取已经当前模板开启的无分组客户、或无分组线索
            Map<Long, Long> formIdNoGroupMap = new HashMap<>();
            //获取已经当前模板开启的无分组客户、或无分组线索
            publicSeniorRuleHelp.getSpecialGroupIdMap(formIdAllGroupIdMap,formIdOpenGroupIdMap,formIdDeleteGroupIdMap, formIdNoGroupMap,corpid,formIdIn);

            //核心逻辑
            for (TransferBackRuleSeniorEntity rule : ruleSeniorList) {
                Long formId = rule.getFormId();
                Map<String, Integer> explainOpenMap = formIdExplainMap.getOrDefault(formId,new HashMap<>());
                List<Long> labelIds = formIdLabelIdMap.getOrDefault(formId,new ArrayList<>());
                List<PublicGroupSeniorEntity> allGroupList = formIdAllGroupIdMap.getOrDefault(formId, new ArrayList<>());
                List<Long> openGroupIdList = formIdOpenGroupIdMap.getOrDefault(formId, new ArrayList<>());
                List<Long> deleteGroupIdList = formIdDeleteGroupIdMap.getOrDefault(formId, new ArrayList<>());
                Long noGroupId = formIdNoGroupMap.getOrDefault(formId, 0L);
                //获取当前模板公海池的客户线索id集合
                Long totalCount = publicSeniorRuleHelp.getPublicCountByForm(corpid, businessType, formId);
                LOG.warn("当前模板的公海池数据总数：totalCount{}", totalCount);
                int pageSize = 1000;
                Long gtId = 0L;
                int pageNum = (int) (totalCount % pageSize > 0 ? totalCount / pageSize + 1 : totalCount / pageSize);
                for (int currentPage = 1; currentPage <= pageNum; currentPage++) {
                    List<Long> dataIdIn = publicSeniorRuleHelp.getDataIdList4Public(gtId,corpid, rule.getFormId(), BasicConstant.ONE, businessType, pageSize);
                    if (CollectionsUtil.isEmpty(dataIdIn)) {
                        break;
                    }
                    gtId = dataIdIn.get(dataIdIn.size() - 1);
                    List<RuleSeniorEntity> backClueList = new ArrayList<>();
                    try {
                        if (transfer) {
                            backClueList = checkSeniorTransferRule.getSeniorBackClueList(null, rule, dataIdIn, null,explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                            if (CollectionsUtil.isNotEmpty(backClueList)) {
                                transfer2SeniorPublic(corpid, backClueList, businessType);
                                pushTransferMessage(userEntity, backClueList, businessType, groupSeniorList);
                            }
                            if (notify) {
                                List<RuleSeniorEntity> notifyClueList = checkSeniorTransferRule.getSeniorBackClueList(null, rule, dataIdIn, advanceTime,explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                                if(CollectionsUtil.isNotEmpty(backClueList) && CollectionsUtil.isNotEmpty(notifyClueList)){
                                    //去除已经转移的线索
                                    List<Long> backIds = backClueList.stream().map(RuleSeniorEntity::getId).collect(Collectors.toList());
                                    notifyClueList = notifyClueList.stream().filter(item -> !backIds.contains(item.getId())).collect(Collectors.toList());
                                }
                                if (CollectionsUtil.isNotEmpty(notifyClueList)) {
                                    tagBackOrTransferPublic(corpid, notifyClueList, businessType, ruleType);
                                    pushTransferTagMessage(groupSeniorList, userEntity, notifyClueList, businessType, isPushGroupManager, isPushGroupUser);
                                }
                            }
                        }
                    } catch (XbbException e) {
                        LOG.error("corpid:" + corpid + "当前报错页数:{}" + currentPage, e);
                    }
                }
            }
            try {
                //一个公司操作完成，移除已打标签客户缓存
                paasRedisHelper.removeValue(RedisPrefixConstant.TAG_LINK_TRANSFER_CLUE_ID, corpid);
            } catch (Exception e) {
                LOG.error("即将转移公海池 标签索引出错！公司Id：" + corpid);
            }
        } catch (Exception e) {
            LOG.error("seniorTransferToPublic4Clue中出现了奇怪的异常, corpid:" + corpid, e);
        }
    }

    /**
     * 退回动作，更新主表和相关团队
     * @param user 当前用户
     * @param retList 需要退回和转移的实体列表
     * @param businessType  业务类型
     */
    public void return2SeniorPublic(UserEntity user,List<RuleSeniorEntity> retList,Integer businessType) {
        String corpid = user.getCorpid();
        List<Long> customerIdList = new ArrayList<>();
        TagTypeEnum tagTypeEnum = TagTypeEnum.PUBLIC_CUSTOMER_RULE;
        if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            tagTypeEnum = TagTypeEnum.PUBLIC_CLUE_RULE;
        }
        for (RuleSeniorEntity entity : retList) {
            customerIdList.add(entity.getId());
            //团队操作
            Map<String, Object> param = userBack2public(entity, user, entity.getObjectGroupId(), businessType);
            if ((int) param.get("code") == 1) {
                try {
                    //日志
                    String opObjectId = entity.getId().toString();
                    String customerName = entity.getName();
                    String formName = entity.getFormName() == null ? "" : entity.getFormName();
                    String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CUSTOMER_RULE_BACK), entity.getRuleName(), formName, customerName);
                    mongoLogHelp.buildLog(corpid, PaasConstant.SYS_USER_ID, I18nMessageUtil.getMessage(PaasConstant.SYS_OPERATING), OperateModuleTypeEnum.OpenSeaRules, OperateTypeEnum.RETURN_TO_PUBLIC, opObjectId, customerName, memo, null);
                } catch (Exception e) {
                    LOG.error("日志记录失败", e);
                }
            }
        }
        // 删除已经退回公海池客户的"即将退回公海池"的标签
        tagLinkModel.deleteTagByTagTypeAndRefIdIn(user.getCorpid(), tagTypeEnum.getCode(), customerIdList);
    }

    /**
     * 转移动作，更新主表所属公海分组字段，其他没有任何变动
     * @param corpid 公司id
     * @param retList 转移的实体列表
     * @param businessType  业务类型
     */
    public void transfer2SeniorPublic(String corpid,List<RuleSeniorEntity> retList,Integer businessType) {
        List<Long> customerIdList = new ArrayList<>();
        TagTypeEnum tagTypeEnum = TagTypeEnum.TRANSFER_CUSTOMER_RULE;
        if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            tagTypeEnum = TagTypeEnum.TRANSFER_CLUE_RULE;
        }
        for (RuleSeniorEntity entity : retList) {
            customerIdList.add(entity.getId());
            try{
                //所属公海字段更新成目标公海分组
                updatePublicGroup(entity,corpid,businessType);
            }catch(XbbException e){
                LOG.error("转移公海分组失败", e);
            }
            try {
                //日志
                String opObjectId = entity.getId().toString();
                String customerName = entity.getName();
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CUSTOMER_RULE_TRANSFER), entity.getRuleName(),
                        entity.getFormName(),customerName,entity.getPublicGroupName(),entity.getObjectGroupName());
                mongoLogHelp.buildLog(corpid, PaasConstant.SYS_USER_ID, I18nMessageUtil.getMessage(PaasConstant.SYS_OPERATING), OperateModuleTypeEnum.OpenSeaRules, OperateTypeEnum.TRANSFER_TO_PUBLIC, opObjectId, customerName, memo, null);
            } catch (Exception e) {
                LOG.error("日志记录失败", e);
            }
        }
        // 删除已经退回公海池客户的"即将转移公海池"的标签
        tagLinkModel.deleteTagByTagTypeAndRefIdIn(corpid, tagTypeEnum.getCode(), customerIdList);
    }

    /**
     * 客户或线索转移公海分组之后，所属公海字段更新成目标公海分组
     * @param entity 需要转移的客户或者线索
     * @param corpid 公司id
     * @param businessType 业务类型
     */
    public void updatePublicGroup(RuleSeniorEntity entity, String corpid, Integer businessType) throws XbbException {

        String publicDateAttr =  CustomerManagementEnum.BACK_PUBLIC_DATE.getAttr();
        String publicGroup =  CustomerManagementEnum.PUBLIC_GROUP.getAttr();

        if (Objects.equals(XbbRefTypeEnum.CLUE.getCode(),businessType)) {
            publicDateAttr =  ClueEnum.BACK_PUBLIC_DATE.getAttr();
            publicGroup =  ClueEnum.PUBLIC_GROUP.getAttr();
        }
        List<UpdateDataEntity> updateDataEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        JSONObject temp = new JSONObject();
        temp.put(publicDateAttr, DateTimeUtil.getInt());
        String publicGroupId = entity.getPublicGroupId();
        String objectGroupId = entity.getObjectGroupId();
        /**
         * 1、如果当前绑定的分组和目标分组一样，则不执行更新;
         * 2、如果publicGroupId = "" 或者 publicGroupId = null,代表当前分组是无公海分组，都是无公海分组则不执行更新
         */
        boolean isUpdate = Objects.equals(publicGroupId,objectGroupId) || (StringUtil.isEmpty(publicGroupId) && StringUtil.isEmpty(objectGroupId));
        if (isUpdate){
            return;
        }
        //如果目标公海为null，代表目标公海分组是无公海分组,删除所属公海字段
        if (StringUtil.isEmpty(objectGroupId)){
            temp.put(publicGroup,"");
        }else {
            temp.put(publicGroup,objectGroupId);
        }
        UpdateDataEntity updateData = ExplainUtil.getUpdateData(entity.getId(), temp, corpid);
        updateDataEntityList.add(updateData);

        //批量更新
        if (CollectionsUtil.isNotEmpty(updateDataEntityList)) {
            proUpdateHelp.updateBatch(1, businessType, corpid, updateDataEntityList);
        }
    }


    /**
     * 退回动作，更新主表和相关团队
     * @param entity 退回实体
     * @param user 当前用户
     * @param groupId 目标公海分组id
     * @param businessType 业务类型
     * @return
     */
    private Map<String, Object> userBack2public(RuleSeniorEntity entity, UserEntity user, String groupId, Integer businessType) {
        String userId = user.getUserId();
        String corpid = user.getCorpid();
        Long dataId = entity.getId();
        Map<String, Object> retMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> dataIdList = new ArrayList<>();
        param.put("userId", userId);
        param.put("corpid", corpid);
        param.put("del", 0);
        Integer count = 0;
        dataIdList.add(dataId);
        if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
            param.put("customerId", dataId);
            count = customerUserModel.getEntitysCount(param);
        }else if(Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())){
            param.put("clueId", dataId);
            count = clueUserModel.getEntitysCount(param);
        }
        if (Objects.equals(count, 0)) {
            retMap.put("code", UserTeamErrorCodeEnum.API_ERROR_390004.getCode());
            retMap.put("msg", UserTeamErrorCodeEnum.API_ERROR_390004.getMsg());
            return retMap;
        }

        boolean flag = false;
        try {
            if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
                flag = userTeamService.updateCustomerTeam(user, dataIdList, UpdateCustomerTeamScenesEnum.PUBLIC_RULE_SCRIPT,entity.getFormId(), SaasMarkEnum.SAAS.getCode(),businessType,DistributorMarkEnum.OTHER.getCode(),groupId);
            }else if(Objects.equals(businessType, XbbRefTypeEnum.CLUE.getCode())){
                flag = userTeamService.updateClueTeam(user, dataIdList, UpdateCustomerTeamScenesEnum.PUBLIC_RULE_SCRIPT,entity.getFormId(), SaasMarkEnum.SAAS.getCode(),businessType,DistributorMarkEnum.OTHER.getCode(),groupId);
            }
        } catch (XbbException e) {
            LOG.error("updateCustomerTeam error", e);
            flag = false;
        }
        if (flag) {
            retMap.put("code", ErrorCodeEnum.API_SUCCESS.getCode());
            retMap.put("msg", ErrorCodeEnum.API_SUCCESS.getMsg());
        } else {
            retMap.put("code", ErrorCodeEnum.API_FAIL.getCode());
            retMap.put("msg", ErrorCodeEnum.API_FAIL.getMsg());
        }
        return retMap;
    }

    /**
     * 客户和线索：给用户发送退回公海的提醒信息
     *
     * @param user        用户对象
     * @param entityList 符合退回规则的客户或者线索列表
     * @author 章华隽
     * 创建时间： 2017/8/17 下午16:14
     * 修改时间： 2022/4/26
     */
    public void pushReturnMessage(UserEntity user, List<RuleSeniorEntity> entityList,Integer businessType) {
        if (CollectionsUtil.isEmpty(entityList)) {
            return;
        }
        RuleSeniorEntity entity = entityList.get(0);
        String name = entity.getName();
        String ruleName = entity.getRuleName();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.CUSTOMER_PUBLIC;
        PushTypeEnum pushTypeEnum = PushTypeEnum.CUSTOMER_BACK_PUBLIC;
        PushTypeEnum messagePushTypeEnum = PushTypeEnum.CUSTOMER_BACK_PUSH;
        String title = I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_BACK_TITLE);
        Entity tempEntity = new CustomerEntityExt();
        String content = "";
        if (entityList.size() > 1) {
            content = String.format(I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_BACK_MORE), name, entityList.size(), ruleName);
        } else {
            content = String.format(I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_BACK), name, ruleName);
        }
        if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            xbbRefTypeEnum = XbbRefTypeEnum.CLUE_PUBLIC;
            messagePushTypeEnum =  PushTypeEnum.CLUE_BACK_PUSH;
            pushTypeEnum = PushTypeEnum.CLUE_BACK_PUSH;
            title = I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_BACK_TITLE);
            tempEntity = new ClueEntityExt();
            if (entityList.size() > 1) {
                content = String.format(I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_BACK_MORE), name, entityList.size(), ruleName);
            } else {
                content = String.format(I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_BACK), name, ruleName);
            }
        }
        pushMessage(user, entityList, title, content, pushTypeEnum,messagePushTypeEnum,xbbRefTypeEnum,tempEntity,null,null,0L);
    }

    /**
     * 客户和线索：给用户发送转移公海的提醒信息
     *
     * @param user      用户对象
     * @param entityList 符合退回规则的客户或者线索列表
     * @param businessType 业务类型
     * @param groupSeniorList 该模板开启的分组列表
     * @author 杨磊
     * 创建时间： 2022/5/12 下午16:14
     */
    public void pushTransferMessage(UserEntity user, List<RuleSeniorEntity> entityList,Integer businessType,List<PublicGroupSeniorEntity> groupSeniorList) {
        if (CollectionsUtil.isEmpty(entityList)) {
            return;
        }
        RuleSeniorEntity entity = entityList.get(0);
        String name = entity.getName();
        String ruleName = entity.getRuleName();
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.CUSTOMER_PUBLIC;
        PushTypeEnum messagePushTypeEnum = PushTypeEnum.CUSTOMER_TRANSFER_PUSH;
        PushTypeEnum pushTypeEnum = PushTypeEnum.CUSTOMER_TRANSFER_PUBLIC;
        String title = I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_TRANSFER_TITLE);
        String content = "";
        Entity tempEntity = new CustomerEntityExt();
        if (entityList.size() > 1) {
            content = String.format(I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_TRANSFER_MORE), name, entityList.size(), ruleName,"");
        } else {
            content = String.format(I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_TRANSFER), name, ruleName,entity.getObjectGroupName());
        }
        if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            xbbRefTypeEnum = XbbRefTypeEnum.CLUE_PUBLIC;
            messagePushTypeEnum =  PushTypeEnum.CLUE_TRANSFER_PUSH;
            pushTypeEnum =  PushTypeEnum.CLUE_TRANSFER_PUBLIC;
            title = I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_TRANSFER_TITLE);
            tempEntity = new ClueEntityExt();
            if (entityList.size() > 1) {
                content = String.format(I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_TRANSFER_MORE), name, entityList.size(), ruleName,"");
            } else {
                content = String.format(I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_TRANSFER), name, ruleName,entity.getObjectGroupName());
            }
        }
        //获取当前表单模板的无公海分组的id
        if (CollectionsUtil.isNotEmpty(groupSeniorList)){
            groupSeniorList = groupSeniorList.stream().filter(e -> Objects.equals(e.getFormId(),entity.getFormId())).collect(Collectors.toList());
        }
        Long noPublicGroupId = getNoPublicGroupId(groupSeniorList);
        //获取公海分组的id和分组成员映射
        Map<Long, Set<String>> managerGroupPushMap = getManagerGroupPushMap(groupSeniorList, user.getCorpid(), true);

        pushMessage(user, entityList, title, content, pushTypeEnum,messagePushTypeEnum, xbbRefTypeEnum,tempEntity,managerGroupPushMap,null,noPublicGroupId);
    }


    /**
     * 为即将退回或者转移公海池的客户或者线索打上标签
     * @param corpid 公司id
     * @param entityList 即将退回公海池的客户列表
     * @param businessType 区分客户和线索
     * @param ruleType 区分退回和转移
     */
    public void tagBackOrTransferPublic(String corpid, List<RuleSeniorEntity> entityList,Integer businessType,Integer ruleType) {
        TagEntity publicTag = null;
        XbbRefTypeEnum xbbRefTypeEnum = null;
        Map<Long, TagLinkEntity> idTagLinkMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        if (CollectionsUtil.isEmpty(entityList)) {
            return ;
        }
        Set<Long> set = new HashSet<>();
        for (RuleSeniorEntity entity : entityList) {
            set.add(entity.getId());
        }

        if(Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode()) && Objects.equals(ruleType,CustomerSeniorRuleTypeEnum.BACK_RULE.getCode())){
            publicTag = tagModel.findReturnPublicTag(TagTypeEnum.PUBLIC_CUSTOMER_RULE.getCode());
            idTagLinkMap  =  getCustomerIdTagLinkMap(corpid,set,XbbRefTypeEnum.CUSTOMER_PUBLIC, RedisPrefixConstant.TAG_LINK_CUSTOMER_ID);
            xbbRefTypeEnum = XbbRefTypeEnum.CUSTOMER_MANAGEMENT;
        }else if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode()) && Objects.equals(ruleType,ClueSeniorRuleTypeEnum.BACK_RULE.getCode())){
            publicTag = tagModel.findReturnPublicTag(TagTypeEnum.PUBLIC_CLUE_RULE.getCode());
            idTagLinkMap = getClueIdTagLinkMap(corpid,set,XbbRefTypeEnum.CLUE_PUBLIC,RedisPrefixConstant.TAG_LINK_CLUE_ID);
            xbbRefTypeEnum = XbbRefTypeEnum.CLUE;
        }else if(Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode()) && Objects.equals(ruleType,CustomerSeniorRuleTypeEnum.TRANSFER_RULE.getCode())){
            publicTag = tagModel.findReturnPublicTag(TagTypeEnum.TRANSFER_CUSTOMER_RULE.getCode());
            idTagLinkMap = getCustomerIdTagLinkMap(corpid,set,XbbRefTypeEnum.CUSTOMER_TRANSFER,RedisPrefixConstant.TAG_LINK_TRANSFER_CUSTOMER_ID);
            xbbRefTypeEnum = XbbRefTypeEnum.CUSTOMER_MANAGEMENT;
        }else if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode()) && Objects.equals(ruleType,ClueSeniorRuleTypeEnum.TRANSFER_RULE.getCode())){
            publicTag = tagModel.findReturnPublicTag(TagTypeEnum.TRANSFER_CLUE_RULE.getCode());
            idTagLinkMap = getClueIdTagLinkMap(corpid,set,XbbRefTypeEnum.CLUE_TRANSFER,RedisPrefixConstant.TAG_LINK_TRANSFER_CLUE_ID);
            xbbRefTypeEnum = XbbRefTypeEnum.CLUE;
        }

        if (publicTag == null) {
            return ;
        }

        ArrayList<TagLinkEntity> updateTagLinkList = new ArrayList<>();
        ArrayList<TagLinkEntity> insertTagLinkList = new ArrayList<>();
        for (RuleSeniorEntity entity : entityList) {
            String newMemo = entity.getNotifyMemo();
            Long id = entity.getId();
            TagLinkEntity tagLink = null;
            if(idTagLinkMap.containsKey(id)){
                tagLink = idTagLinkMap.get(id);
                //更新标签
                tagLink.setMemo(newMemo);
                updateTagLinkList.add(tagLink);
            }else{
                tagLink = new TagLinkEntity(corpid, "", publicTag, id, xbbRefTypeEnum, newMemo);
                //第一次添加标签
                insertTagLinkList.add(tagLink);
            }
        }
        if(CollectionsUtil.isNotEmpty(insertTagLinkList)){
            tagLinkModel.batchInsert(insertTagLinkList);
        }
        if(CollectionsUtil.isNotEmpty(updateTagLinkList)){
            tagLinkModel.batchUpdate(updateTagLinkList);
        }
    }

    /**
     * 获取客户列表notifyCustomerList中，有tagLink的的map
     *
     * @param corpid
     * @param customerIdSet 需要提醒的客户列表
     * @param xbbRefTypeEnum 区分退回和转移
     * @param filePrefix 转移和退回的redis前缀
     */
    private Map<Long, TagLinkEntity> getCustomerIdTagLinkMap(String corpid, Set<Long> customerIdSet,XbbRefTypeEnum xbbRefTypeEnum,String filePrefix) {
        Set<Long> allCustomerId = new HashSet<>();

        Set<Long> tagLinkCustomerIdSet = new HashSet<>(16);
        Set<Integer> tagLinkCustomerIdRedis = null;
        try {
            //这边会被转化成Integer
            tagLinkCustomerIdRedis = paasRedisHelper.getValue4Set(filePrefix, corpid);
        } catch (Exception e) {
            // ignore
        }
        if(tagLinkCustomerIdRedis != null){
            for (Integer customerId : tagLinkCustomerIdRedis) {
                tagLinkCustomerIdSet.add(customerId.longValue());
            }
        }

        Map<Long, TagLinkEntity> retMap = new HashMap<>(16);

        allCustomerId.addAll(tagLinkCustomerIdSet);
        allCustomerId.addAll(customerIdSet);

        //取交集
        customerIdSet.retainAll(tagLinkCustomerIdSet);
        List<Long> customerIdIn = new ArrayList<>(customerIdSet);
        if (customerIdIn.size() != 0) {
            List<TagLinkEntity> list = tagLinkModel.getCompanyTagLinksByRefType(corpid, xbbRefTypeEnum.getCode(), customerIdIn);
            for(TagLinkEntity tagLink : list){
                retMap.put(tagLink.getRefId(), tagLink);
            }
        }

        paasRedisHelper.setValue4Set(filePrefix, corpid, allCustomerId, 2 * 3600);
        return retMap;
    }

    /**
     * 获取线索列表notifyCustomerList中，有tagLink的的map
     *
     * @param corpid
     * @param clueIdSet 需要提醒的线索列表
     * @param xbbRefTypeEnum 区分退回和转移
     * @param filePrefix 转移和退回的redis前缀
     */
    private Map<Long, TagLinkEntity> getClueIdTagLinkMap(String corpid, Set<Long> clueIdSet,XbbRefTypeEnum xbbRefTypeEnum,String filePrefix) {
        Set<Long> allClueId = new HashSet<>();

        Set<Long> tagLinkClueIdSet = new HashSet<>(16);
        Set<Integer> tagLinkClueIdRedis = null;
        try {
            //这边会被转化成Integer
            tagLinkClueIdRedis = paasRedisHelper.getValue4Set(filePrefix, corpid);
        } catch (Exception e) {
            // ignore
        }
        if(tagLinkClueIdRedis != null){
            for (Integer clueId : tagLinkClueIdRedis) {
                tagLinkClueIdSet.add(clueId.longValue());
            }
        }

        Map<Long, TagLinkEntity> retMap = new HashMap<>(16);

        allClueId.addAll(tagLinkClueIdSet);
        allClueId.addAll(clueIdSet);

        //取交集
        clueIdSet.retainAll(tagLinkClueIdSet);
        List<Long> clueIdIn = new ArrayList<>(clueIdSet);
        if (clueIdIn.size() != 0) {
            List<TagLinkEntity> list = tagLinkModel.getCompanyTagLinksByRefType(corpid, xbbRefTypeEnum.getCode(), clueIdIn);
            for(TagLinkEntity tagLink : list){
                retMap.put(tagLink.getRefId(), tagLink);
            }
        }

        paasRedisHelper.setValue4Set(filePrefix, corpid, allClueId, 2 * 3600);
        return retMap;
    }


    /**
     * 给用户发送即将退回公海的标签的提醒信息
     *
     * @param user         用户对象
     * @param entityList 符合提醒规则的客户或者线索列表
     * @param businessType 区分客户和线索
     */
    public void pushBackTagMessage(UserEntity user, List<RuleSeniorEntity> entityList,Integer businessType) {
        if (CollectionsUtil.isEmpty(entityList)) {
            return;
        }
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.CUSTOMER;
        PushTypeEnum messagePushTypeEnum = PushTypeEnum.CUSTOMER_WILL_BACK_PUSH;
        PushTypeEnum pushTypeEnum = PushTypeEnum.CUSTOMER_BACK_PUBLIC;
        String title = I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_WILL_BACK_TITLE);
        Entity tempEntity = new CustomerEntityExt();
        Map<Long, List<RuleSeniorEntity>> leftDayMap = entityList.stream().collect(Collectors.groupingBy(RuleSeniorEntity::getLeftDay));
        String pushConstant = CustomerBackPushConstant.CUSTOMER_WILL_BACK;
        String batchPushConstant = CustomerBackPushConstant.CUSTOMER_WILL_BACK_MORE;
        if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            xbbRefTypeEnum = XbbRefTypeEnum.ALL_CLUE;
            messagePushTypeEnum =  PushTypeEnum.CLUE_WILL_BACK_PUSH;
            pushTypeEnum =  PushTypeEnum.CLUE_BACK_PUBLIC;
            title = I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_WILL_BACK_TITLE);
            tempEntity = new ClueEntityExt();
            pushConstant = ClueBackPushConstant.CLUE_WILL_BACK;
            batchPushConstant = ClueBackPushConstant.CLUE_WILL_BACK_MORE;
        }
        for(Map.Entry<Long,List<RuleSeniorEntity>> entry : leftDayMap.entrySet()){
            String content;
            List<RuleSeniorEntity> valueList = entry.getValue();
            String name = valueList.get(0).getName();
            if (valueList.size() > 1){
                content = String.format(I18nMessageUtil.getMessage(batchPushConstant), name, entry.getValue().size(), entry.getKey());
            }else {
                content = String.format(I18nMessageUtil.getMessage(pushConstant), name, entry.getKey());
            }
            pushMessage(user,valueList, title, content, pushTypeEnum,messagePushTypeEnum,xbbRefTypeEnum,tempEntity,null,null,0L);
        }
    }

    /**
     * 给用户发送即将转移公海的标签的提醒信息
     *
     * @param user         用户对象
     * @param entityList 符合提醒规则的客户或者线索列表
     * @author 杨磊
     * 创建时间： 2022/5/13 下午16:14
     * @since 1.0
     */
    public void pushTransferTagMessage(List<PublicGroupSeniorEntity> groupSeniorList,UserEntity user, List<RuleSeniorEntity> entityList,Integer businessType,boolean isPushGroupManager,boolean isPushGroupUser) {
        if (CollectionsUtil.isEmpty(entityList)) {
            return;
        }
        RuleSeniorEntity entity = entityList.get(0);
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.CUSTOMER_PUBLIC;
        Entity tempEntity = new CustomerEntityExt();
        PushTypeEnum pushTypeEnum = PushTypeEnum.CUSTOMER_TRANSFER_PUBLIC;
        PushTypeEnum messagePushTypeEnum = PushTypeEnum.CUSTOMER_WILL_TRANSFER_PUSH;
        String title = I18nMessageUtil.getMessage(CustomerBackPushConstant.CUSTOMER_WILL_TRANSFER_TITLE);
        String pushConstant = CustomerBackPushConstant.CUSTOMER_WILL_TRANSFER;
        String batchPushConstant = CustomerBackPushConstant.CUSTOMER_WILL_TRANSFER_MORE;
        if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            xbbRefTypeEnum = XbbRefTypeEnum.CLUE_PUBLIC;
            messagePushTypeEnum = PushTypeEnum.CLUE_WILL_TRANSFER_PUSH;
            pushTypeEnum =  PushTypeEnum.CLUE_TRANSFER_PUBLIC;
            title = I18nMessageUtil.getMessage(ClueBackPushConstant.CLUE_WILL_TRANSFER_TITLE);
            tempEntity = new ClueEntityExt();
            pushConstant = ClueBackPushConstant.CLUE_WILL_TRANSFER;
            batchPushConstant = ClueBackPushConstant.CLUE_WILL_TRANSFER_MORE;
        }
        //获取当前表单模板的无公海分组的id
        if (CollectionsUtil.isNotEmpty(groupSeniorList)){
            groupSeniorList = groupSeniorList.stream().filter(e -> Objects.equals(e.getFormId(),entity.getFormId())).collect(Collectors.toList());
        }
        Long noPublicGroupId = getNoPublicGroupId(groupSeniorList);
        //获取公海分组的id和分组成员映射
        Map<Long, Set<String>> managerGroupPushMap = getManagerGroupPushMap(groupSeniorList, user.getCorpid(), isPushGroupManager);
        Map<Long, Set<String>> userGroupPushMap = getUserGroupPushMap(groupSeniorList, user.getCorpid(), isPushGroupUser);
        Map<Long, List<RuleSeniorEntity>> leftDayMap = entityList.stream().collect(Collectors.groupingBy(RuleSeniorEntity::getLeftDay));
        for(Map.Entry<Long,List<RuleSeniorEntity>> entry : leftDayMap.entrySet()){
            String content;
            List<RuleSeniorEntity> valueList = entry.getValue();
            String name = valueList.get(0).getName();
            if (valueList.size() > 1){
                content = String.format(I18nMessageUtil.getMessage(batchPushConstant), name, entry.getValue().size(), entry.getKey());
            }else {
                content = String.format(I18nMessageUtil.getMessage(pushConstant), name, entry.getKey());
            }
            //发消息动作
            pushMessage(user, entityList, title, content, pushTypeEnum,messagePushTypeEnum, xbbRefTypeEnum,tempEntity,managerGroupPushMap,userGroupPushMap,noPublicGroupId);
        }
    }

    /**
     * 获取每个分组管理员的userId
     * @param groupSeniorList 所有分组列表
     * @param corpid 该公司id
     * @param isManager 是否推送给分组管理
     * @return
     */
    public Map<Long, Set<String>> getManagerGroupPushMap(List<PublicGroupSeniorEntity> groupSeniorList,String corpid,boolean isManager){
        //分组id和该分组管理员的map
        Map<Long, Set<String>> idToPushGroupMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for(PublicGroupSeniorEntity groupSenior : groupSeniorList){
            //该分组的分组管理员或成员的权限
            if (isManager){
                publicSeniorRuleHelp.getUserIdsByScopeRule(groupSenior.getAdminScopeRule(),corpid,idToPushGroupMap,groupSenior.getId());
            }
        }
        return idToPushGroupMap;
    }

    /**
     * 获取分组成员的userId
     * @param groupSeniorList 所有分组列表
     * @param corpid 公司id
     * @param isUser 是否推送给分组成员
     * @return
     */
    public Map<Long, Set<String>> getUserGroupPushMap(List<PublicGroupSeniorEntity> groupSeniorList,String corpid,boolean isUser){
        //分组id和该分组管理员的map
        Map<Long, Set<String>> idToPushGroupMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for(PublicGroupSeniorEntity groupSenior : groupSeniorList){
            //该分组的分组管理员或成员的权限
            if (isUser){
                publicSeniorRuleHelp.getUserIdsByScopeRule(groupSenior.getScopeRule(),corpid,idToPushGroupMap,groupSenior.getId());
            }
        }
        return idToPushGroupMap;
    }
    /**
     * 获取当前表单模板的无公海分组的id
     * @param groupSeniorList
     * @return
     */
    public Long getNoPublicGroupId(List<PublicGroupSeniorEntity> groupSeniorList){
        Long noGroupId = 0L;
        Optional<PublicGroupSeniorEntity> optional = groupSeniorList.stream().filter(e -> Objects.equals(e.getGroupType(), BasicConstant.TWO)).findAny();
        if (optional.isPresent()){
            noGroupId = optional.get().getId();
        }
        return noGroupId;
    }


    /**
     * 给用户发送即将退回或转移公海的提醒信息
     * @param user         用户对象
     * @param entityList 符合提醒规则的客户或线索列表
     * @param title  消息标题
     * @param content 消息内容
     * @param pushTypeEnum 推送对象
     * @param messagePushTypeEnum 推送对象
     * @param xbbRefTypeEnum 符合提醒规则的客户或线索列表
     * @param managerPushMap 公海分组id -> 该分组分组管理员映射
     * @param userPushMap 公海分组id -> 该分组分组成员映射
     * @param noGroupId 无公海分组id
     * @version
     */
    private void pushMessage(UserEntity user, List<RuleSeniorEntity> entityList, String title, String content,
                             PushTypeEnum pushTypeEnum, PushTypeEnum messagePushTypeEnum,XbbRefTypeEnum xbbRefTypeEnum,Entity entity, Map<Long, Set<String>> managerPushMap,Map<Long, Set<String>> userPushMap,Long noGroupId) {
        RuleSeniorEntity ruleSenior = entityList.get(0);
        Long appId = ruleSenior.getAppId();
        Long menuId = ruleSenior.getMenuId();
        try {
            String corpid = user.getCorpid();
            String userId = user.getUserId();

            List<Long> refIds = new ArrayList<>();
            Set<String> pushGroupSet = new HashSet<>();
            for (RuleSeniorEntity ruleSeniorEntity : entityList) {
                refIds.add(ruleSeniorEntity.getId());
                String publicGroupId = ruleSeniorEntity.getPublicGroupId();
                if (Objects.nonNull(managerPushMap)){
                    if (StringUtil.isEmpty(publicGroupId)){
                        pushGroupSet.addAll(managerPushMap.getOrDefault(noGroupId,new HashSet<>()));
                    }else {
                        pushGroupSet.addAll(managerPushMap.getOrDefault(Long.parseLong(publicGroupId),new HashSet<>()));
                    }
                }
                if (Objects.nonNull(userPushMap)){
                    if (StringUtil.isEmpty(publicGroupId)){
                        pushGroupSet.addAll(userPushMap.getOrDefault(noGroupId,new HashSet<>()));
                    }else {
                        pushGroupSet.addAll(userPushMap.getOrDefault(Long.parseLong(publicGroupId),new HashSet<>()));
                    }
                }
            }
            Integer remind = 0;
            Long pushTime = DateTimeUtil.getTodayInt() + 32400;
            List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, pushTypeEnum.getCode(), pushTypeEnum.getSubCode(), user, entity);
            if (userId != null){
                pushUserList.add(userId);
            }
            pushUserList.addAll(pushGroupSet);
            PushRefTypePojo.Options options = new PushRefTypePojo.Options(appId, menuId, refIds, SaasMarkEnum.SAAS.getCode(), xbbRefTypeEnum.getCode());
            if(CollectionsUtil.isNotEmpty(pushUserList)){
                MessageRabbitMqDTO messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, refIds, remind, pushTime, title, content, null, options);
                messageService.insertPushData(messageRabbitMqDTO, messagePushTypeEnum);
            }
        } catch (Exception e) {
            LOG.error("消息入库失败", e);
        }
    }

    /**
     * 转移推送规则：获取推送分组管理员和成员
     * @param corpid
     * @param pushTypeEnum
     * @return
     */
    public boolean getIsPushByAlias(String corpid,PushTypeEnum pushTypeEnum,String pushAlias,Integer businessType) {
        CustomerPushSet customerPushSet = new CustomerPushSet();
        boolean isPush = false;
        PushSetEntity pushSetEntity = customerPushSet.getPushSet(corpid, pushTypeEnum.getSubCode(), pushSetModel);
        if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
            CluePushSet cluePushSet = new CluePushSet();
            pushSetEntity  = cluePushSet.getPushSet(corpid, pushTypeEnum.getSubCode(), pushSetModel);
        }
        String pushObjectString = pushSetEntity.getPushObject();
        if (Objects.equals(pushSetEntity.getEnable(), 1)) {
            JSONObject pushObject = JsonHelperUtil.parseObject(pushObjectString);
            String typeString = pushObject.getString("type");
            JSONArray typeJsonArray = JsonHelperUtil.parseArray(typeString);
            for (Object object : typeJsonArray) {
                JSONObject jsonObject = (JSONObject) object;
                Integer enable = jsonObject.getInteger("enable");
                if (Objects.equals(enable, 1)) {
                    String alias = jsonObject.getString("alias");
                    if (Objects.equals(alias, pushAlias)) {
                        isPush = true;
                    }
                }
            }
        }
        return isPush;
    }

    /**
     * 兼容老逻辑
     * @param ruleCustomerEntityList 标准模式客户规则对象
     * @param ruleClueEntityList 标准模式线索规则对象
     * @return
     */
    public List<RuleSeniorEntity> copyBackCustomerList(List<RuleCustomerEntity> ruleCustomerEntityList, List<RuleClueEntity> ruleClueEntityList){
        List<RuleSeniorEntity> ruleSeniorEntityList = new ArrayList<>();
        if (CollectionsUtil.isNotEmpty(ruleCustomerEntityList)){
            for (RuleCustomerEntity entity : ruleCustomerEntityList){
                RuleSeniorEntity ruleSenior = new RuleSeniorEntity();
                BeanUtil.copyProperties(entity,ruleSenior);
                ruleSenior.setRuleName(CustomerSeniorRuleTypeEnum.MAX_CUSTOMER_NUM_RULE.getName());
                ruleSeniorEntityList.add(ruleSenior);
            }
            return  ruleSeniorEntityList;
        }
        if (CollectionsUtil.isNotEmpty(ruleClueEntityList)){
            for (RuleClueEntity entity : ruleClueEntityList){
                RuleSeniorEntity ruleSenior = new RuleSeniorEntity();
                BeanUtil.copyProperties(entity,ruleSenior);
                ruleSenior.setRuleName(ClueSeniorRuleTypeEnum.MAX_CLUE_NUM_RULE.getName());
                ruleSeniorEntityList.add(ruleSenior);
            }
            return  ruleSeniorEntityList;
        }
        return ruleSeniorEntityList;
    }



    /**
     * 公海高级模式 - 更新最新的标签
     * @param corpid 公司id
     * @param refIds 客户或者线索ids
     * @param businessType 业务类型
     * @param formId 表单id
     * @throws XbbException
     */
    @Async(value = "deletePublicSeniorTagThreadPool")
    @Override
    public void deletePublicSeniorTag(String corpid, List<Long> refIds,Integer businessType,Long formId) throws XbbException {
        try {
            // TODO: 2022/9/19 改成队列延时
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            LOG.error("Thread.sleep", e);
            // 恢复中断状态
            Thread.currentThread().interrupt();
        }
        try {
            Integer ruleType = CustomerSeniorRuleTypeEnum.BACK_RULE.getCode();
            //获取公司所有的高级模式已启用的公海退回规则
            List<TransferBackRuleSeniorEntity> ruleSeniorList = transferBackRuleSeniorModel.getTransferBackRuleByType(corpid, formId,
                    businessType, Arrays.asList(ruleType),BasicConstant.ONE);

            Map<Long, String> idMemoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (Long id : refIds) {
                idMemoMap.put(id, "");
            }
            if (CollectionsUtil.isEmpty(ruleSeniorList)){
                return;
            }
            TransferBackRuleSeniorEntity rule = ruleSeniorList.get(BasicConstant.ZERO);

            List<Long> formIdIn = new ArrayList<>();
            ruleSeniorList.forEach(item -> formIdIn.add(item.getFormId()));
            //获取表单字段启用情况
            Map<Long,Map<String, Integer>> formIdExplainMap = publicSeniorRuleHelp.getExplainOpenMap(corpid, formIdIn);
            //获取该表单开启标签列表
            Map<Long, List<Long>> formIdLabelIdMap = publicSeniorRuleHelp.getLabelIds4FormId(corpid,formIdIn);
            //如果模板下的所有分组，包括del = 1 的
            Map<Long,List<PublicGroupSeniorEntity>> formIdAllGroupIdMap = new HashMap<>();
            //获取模板启用并且未删除的分组
            Map<Long,List<Long>> formIdOpenGroupIdMap = new HashMap<>();
            //获取模板已经删除的分组
            Map<Long,List<Long>> formIdDeleteGroupIdMap = new HashMap<>();
            //获取已经当前模板开启的无分组客户、或无分组线索
            Map<Long, Long> formIdNoGroupMap = new HashMap<>();
            //获取已经当前模板开启的无分组客户、或无分组线索
            publicSeniorRuleHelp.getSpecialGroupIdMap(formIdAllGroupIdMap,formIdOpenGroupIdMap,formIdDeleteGroupIdMap, formIdNoGroupMap,corpid,formIdIn);

            Map<String, Integer> explainOpenMap = formIdExplainMap.getOrDefault(formId,new HashMap<>());
            List<Long> labelIds = formIdLabelIdMap.getOrDefault(formId,new ArrayList<>());
            List<PublicGroupSeniorEntity> allGroupList = formIdAllGroupIdMap.getOrDefault(formId, new ArrayList<>());
            List<Long> openGroupIdList = formIdOpenGroupIdMap.getOrDefault(formId, new ArrayList<>());
            List<Long> deleteGroupIdList = formIdDeleteGroupIdMap.getOrDefault(formId, new ArrayList<>());
            Long noGroupId = formIdNoGroupMap.getOrDefault(formId, 0L);

            //获取提醒时间配置
            CompanyConfigEnum companyConfigEnum = CompanyConfigEnum.PUBLIC_RULE_CUSTOMER_SENIOR_REMIND_TIME;
            List<UserEntity> userList = customerUserService.getMainUserList(refIds, corpid, 1);
            if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
                companyConfigEnum = CompanyConfigEnum.PUBLIC_RULE_CLUE_SENIOR_REMIND_TIME;
                userList = clueUserService.getMainUserList(refIds,corpid,1);
            }
            Integer advanceTime = publicSeniorRuleHelp.getRemindTimeByAlias(corpid, companyConfigEnum.getAlias());
            List<Long> refIdList = new ArrayList<>(refIds);
            for(UserEntity user : userList){
                List<RuleSeniorEntity> notifyEntityList = new ArrayList<>();
                if (Objects.equals(businessType,XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())){
                    notifyEntityList = checkSeniorBackRule.getSeniorBackCustomerList(user, rule, refIdList, advanceTime, null,
                            explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                }else if(Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())){
                    notifyEntityList = checkSeniorBackRule.getSeniorBackClueList(user, rule, refIdList, advanceTime,
                            explainOpenMap,labelIds,openGroupIdList,deleteGroupIdList,noGroupId,allGroupList);
                }
                if(CollectionsUtil.isEmpty(notifyEntityList)){
                    continue;
                }
                for (RuleSeniorEntity ruleSenior : notifyEntityList) {
                    String memo = idMemoMap.get(ruleSenior.getId());
                    if (StringUtil.isEmpty(memo)) {
                        memo = "";
                    }

                    if(StringUtil.isEmpty(memo)){
                        memo = ruleSenior.getNotifyMemo();
                    }else{
                        memo += "," + ruleSenior.getNotifyMemo();
                    }
                    idMemoMap.put(ruleSenior.getId(), memo);
                }
            }
            Set<Long> customerIdSet = idMemoMap.keySet();
            for (Long customerId : customerIdSet) {
                String memo = idMemoMap.get(customerId);
                publicSeniorRuleHelp.updateTagLink(corpid, customerId, memo,businessType);
            }
        } catch (Exception e) {
            LOG.error("deletePublicSeniorTag error", e);
        }
    }
}
